home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / cgazv4n2.zip / ANASTACK.C next >
C/C++ Source or Header  |  1989-08-17  |  7KB  |  267 lines

  1. #include <stdio.h>
  2.  
  3. /******************************************************************
  4.  * Module: anastack.c
  5.  * Author: John Rex
  6.  * Compiler: MSC 5.1, TurboC 2.0
  7.  * Memory model: any
  8.  * Purpose: analyze and report on stack usage
  9.  *
  10.  * Usage: For use with MSC 5.1, getsp.asm must be assembled
  11.  *        and linked in.  Then,
  12.  *
  13.  *      void start_anastack(), report_anastack();
  14.  *
  15.  *      .. at beginning of code, in main():
  16.  *         start_anastack();
  17.  *
  18.  *      .. then, whenever desired:
  19.  *         report_anastack("message");
  20.  *
  21.  * The first routine initializes some data areas and writes a unique byte
  22.  * into the stack area.  The second routine then reports on this, labeling
  23.  * the report with the string passed to it.
  24.  *
  25.  * Compile switches:
  26.  *     DEBUG - if == 1, compile a test driver
  27.  *
  28.  * Sources: This code was derived from study of the Turbo C and Microsoft
  29.  *          C run-time libraries and startup code.
  30.  *
  31.  * Source code may be used freely if authorship is acknowledged.
  32.  * Object code may be used freely.
  33.  *************************************************************************/
  34.  
  35. #if defined(__TURBOC__)
  36.     #define TURBO
  37.     #if defined(__SMALL__) || defined(__MEDIUM__) || defined(__TINY__)
  38.         #define TURBOSMALL
  39.     #else
  40.         #define TURBOLARGE
  41.     #endif
  42. #else
  43.     #define MSC
  44. #endif
  45.  
  46. #define DEBUG 1
  47.  
  48. /* define our own pointer manipulation macros */
  49. #define FP_OFF(x) ( (unsigned) x)
  50. #define FP_SEG(x) ( (unsigned) ( ((long) x) >> 16) )
  51. #define MK_FP(seg,off) ((char far *) ( (((long) seg) << 16) + off) )
  52.  
  53. /* the pattern we use in the stack */
  54. #define PATTERN (char) 0xEF
  55.  
  56. #if defined(TURBO)
  57. extern unsigned _stklen;       /* stack length */
  58.  
  59. #else /* Microsoft C */
  60. extern int end;     /* the marker that locates the bottom of the stack */
  61. unsigned getsp();   /* returns current value of SP, the stack pointer  */
  62. #endif
  63.  
  64. /* storage for stack's description */
  65. static char far *stack_bottom;
  66. static char far *stack_top;
  67.  
  68. /* initialize stack area */
  69. void start_anastack()
  70. {
  71.     char far *ptr;
  72.  
  73. #if defined(TURBO)
  74.  
  75. # if defined(TURBOSMALL)
  76.     extern char far *_heapbase; /* Points to beginning of the far heap.
  77.                                  * This location marks the true top of
  78.                                  *   the stack.
  79.                                  */
  80.     long bottom, ss_normal; /* for pointer conversions */
  81.  
  82.     bottom = FP_SEG(_heapbase); /* true top of stack */
  83.     bottom <<= 4;
  84.     bottom -= _stklen;          /* true bottom of stack */
  85.  
  86.     /* now normalize bottom of stack to be SS relative */
  87.     ss_normal = ((long)_SS) << 4;
  88.     bottom -= ss_normal;
  89.     stack_bottom = MK_FP(_SS, ((unsigned) bottom) );
  90.  
  91. # else /* Turbo C Compact, Large, or Huge models */
  92.     stack_bottom = MK_FP(_SS,0); /* This is the simplest case, since in
  93.                                   * these models the stack has its own
  94.                                   * segment.
  95.                                   */
  96. # endif
  97.  
  98.     stack_top = MK_FP(_SS, _SP);  /* Top of usable stack */
  99.  
  100. #else /* Microsoft C */
  101.     stack_bottom = (char far *) &end;   /* end is created by linker
  102.                                            at the bottom of the stack */
  103.     stack_top = MK_FP(FP_SEG(stack_bottom), getsp());
  104. #endif
  105.  
  106.     /* overwrite free stack area */
  107.     for (ptr = stack_bottom; ptr != stack_top; ptr++)
  108.         *ptr = PATTERN;
  109. }
  110.  
  111. /* report on stack usage */
  112. void report_anastack(char *message)
  113. {
  114.     unsigned size, used, now_using;
  115.     char far *been_to, far *now_at;
  116.     int i=0;
  117.  
  118.     /* compute a few things ... */
  119.  
  120.     /* ... size of stack */
  121. #if defined(TURBO)
  122.  
  123. # if defined(TURBOSMALL)
  124.     /* small/medium models--malloc() may actually steal some of the
  125.      * stack's area - must watch for this.
  126.      */
  127.     extern unsigned __brklvl;
  128.  
  129.     size = FP_OFF(stack_top) - __brklvl;
  130.     if (size > _stklen)
  131.         size = _stklen;
  132.  
  133.     if (__brklvl > FP_OFF(stack_bottom))
  134.         /* malloc() has encroached on stack--must reset stack bottom */
  135.         stack_bottom = MK_FP(_SS, __brklvl);
  136.  
  137. # else
  138.     size = _stklen;
  139. # endif
  140.  
  141. #else /* Microsoft C */
  142.     size = FP_OFF(stack_top) - FP_OFF(stack_bottom);
  143. #endif
  144.  
  145.     /* ... amount of stack used so far */
  146.     for (been_to = stack_bottom;
  147.         (*been_to == PATTERN) && (been_to != stack_top); been_to++, i++);
  148.     used = FP_OFF(stack_top) - FP_OFF(been_to);
  149.  
  150.     /* ... where we are now */
  151. #if defined(TURBO)
  152.     now_at = MK_FP(_SS, _SP);
  153. #else
  154.     now_at = MK_FP(FP_SEG(stack_bottom), getsp());
  155. #endif
  156.     now_using = FP_OFF(stack_top) - FP_OFF(now_at);
  157.  
  158.     /* now print report */
  159.     printf("report_anastack(): %s\n", message);
  160.  
  161.     printf("  The stack contains %u bytes and extends from %Fp to %Fp\n",
  162.             size, stack_bottom, stack_top);
  163.  
  164.     printf("  The stack pointer is now at %Fp, using %u bytes (%d%%)\n",
  165.             now_at, now_using, (int) (100L * now_using / size));
  166.  
  167.     printf("  The stack has been as low as %Fp, using %u bytes (%d%%)\n\n",
  168.             been_to, used, (int) (100L * used / size));
  169. }
  170.  
  171. #pragma page()
  172. #if DEBUG==1
  173.  
  174. #include <stdlib.h>
  175. #include <string.h>
  176.  
  177. #if defined(TURBOSMALL)
  178. char *mode;
  179.  
  180. /* a routine to use up the heap */
  181. void tell_more()
  182. {
  183.     extern unsigned __brklvl;
  184.     char *ptr;
  185.     int count;
  186.  
  187.     printf("tell_more:\n");
  188.     printf("  __brklvl is %x\n",__brklvl);
  189.  
  190.     count = 0;
  191.     while((ptr = malloc(1024)) != NULL) {
  192.         memset(ptr,'w',1024);
  193.         count++;
  194.     }
  195.  
  196.     printf("  Able to allocate %d blocks of 1024 bytes\n", count);
  197.     printf("  __brklvl is %x\n\n",__brklvl);
  198. }
  199. #endif
  200.  
  201. /* a routine to use the stack */
  202. void recurse(int i)
  203. {
  204.     if (i == 0) {
  205.         report_anastack("recurse() called with zero");
  206.  
  207. #if defined(TURBOSMALL)
  208.         if (strchr(mode, 'r') != NULL)
  209.             tell_more();
  210. #endif
  211.  
  212.     }
  213.     else
  214.         recurse(i-1);
  215. }
  216.  
  217. /*
  218.  * test driver to demonstrate behavior of stack.  Usage:
  219.  *
  220.  * I. Microsoft C (all models)
  221.  *    Turbo C (Compact, Large, Huge)
  222.  *
  223.  *    Just invoke the .exe file.  No command line options.
  224.  *
  225.  * II. Turbo C (Tiny, Small, Medium)
  226.  *
  227.  *      anastack command
  228.  *
  229.  *    where command may be
  230.  *       (1) Empty (i.e., no string)
  231.  *    or (2) A string containing any or all of the chars "ser".
  232.  *           This string controls calls to tell_more, a routine that
  233.  *           allocates 1024 byte blocks on the heap until there is no
  234.  *           more room.  The letters mean:
  235.  *           's' => call tell_more at start of main()
  236.  *           'e' => call tell_more at end of main()
  237.  *           'r' => call tell_more at bottom of recursive descent
  238.  *    See the text for a discussion of what this demonstrates.
  239.  */
  240.  
  241. void main(int argc, char **argv)
  242. {
  243. #if defined(TURBOSMALL)
  244.     mode = argv[1]; /* controls use of tell_more */
  245. #endif
  246.  
  247.     start_anastack();
  248.  
  249. #if defined(TURBOSMALL)
  250.     if (strchr(mode, 's') != NULL)
  251.         tell_more();
  252. #endif
  253.  
  254.     report_anastack("beginning of main()");
  255.     report_anastack("second call in a row to report_anastack()");
  256.  
  257.     recurse(200);
  258.  
  259. #if defined(TURBOSMALL)
  260.     if (strchr(mode, 'e') != NULL)
  261.         tell_more();
  262. #endif
  263.  
  264.     report_anastack("at end of main()");
  265. }
  266. #endif
  267.